/* EGS primitives: low level routines that write the actual EGS code.
 *
 * Copyright (c) 1993-2007 Leo Spiekman, Xaveer Leijtens
 *
 * This file is part of libMask.
 *
 * libMask is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 *
 * libMask is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with libMask.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "egs.h"

/* Units are specified in meters, but written to egs file in micrometers. */
#define MU(x) ((x)*1e6)
//to avoid error due to SWIG.
/*double MU(double x)
{
  return ((x)*1e6);
}*/

/* Set the current layer */
void egs_layer(int n)
{
  layernr(n);
  clayer=n;
}

void egs_mskpolygon3(int l, double x1, double y1, double x2, double y2,
    double x3, double y3)
{
  if (drawlayer(l)) {
    if (mode & GRIDDED) {
      fprintf(MASK,
	"add p%d :w0.000 %s%.3f,%.3f %.3f,%.3f %.3f,%.3f %.3f,%.3f;\n",
	l,mode&FILLED?":fill ":"",
	MU(x1),MU(y1),MU(x2),MU(y2),MU(x3),MU(y3),MU(x1),MU(y1));
    } else {
      fprintf(MASK,
	"add p%d :w0.000 %s%.4f,%.4f %.4f,%.4f %.4f,%.4f %.4f,%.4f;\n",
	l,mode&FILLED?":fill ":"",
	MU(x1),MU(y1),MU(x2),MU(y2),MU(x3),MU(y3),MU(x1),MU(y1));
    }
  }
}

void egs_mskpolygon4(int l, double x1, double y1, double x2, double y2,
    double x3, double y3, double x4, double y4)
{
  if (drawlayer(l)) {
    if (mode & GRIDDED) {
      fprintf(MASK,
	"add p%d :w0.000 %s%.3f,%.3f %.3f,%.3f %.3f,%.3f %.3f,%.3f %.3f,%.3f;\n",
	l,mode&FILLED?":fill ":"",
	MU(x1),MU(y1),MU(x2),MU(y2),MU(x3),MU(y3),MU(x4),MU(y4),MU(x1),MU(y1));
    } else {
      fprintf(MASK,
	"add p%d :w0.000 %s%.4f,%.4f %.4f,%.4f %.4f,%.4f %.4f,%.4f %.4f,%.4f;\n",
	l,mode&FILLED?":fill ":"",
	MU(x1),MU(y1),MU(x2),MU(y2),MU(x3),MU(y3),MU(x4),MU(y4),MU(x1),MU(y1));
    }
  }
}

void egs_mskpolygonN(int l, double *x, double *y, int n)
{
  int i;

  if (drawlayer(l)) {
    if (mode & GRIDDED) {
      fprintf(MASK, "add p%d :w0.000 %s", l,mode&FILLED?":fill ":"");
      for (i=0; i<n; i++) fprintf(MASK, " %.3f,%.3f", MU(x[i]), MU(y[i]));
      fprintf(MASK, " %.3f,%.3f", MU(x[0]), MU(y[0])); /* close path */
    } else {
      fprintf(MASK, "add p%d :w0.0000 %s", l,mode&FILLED?":fill ":"");
      for (i=0; i<n; i++) fprintf(MASK, " %.4f,%.4f", MU(x[i]), MU(y[i]));
      fprintf(MASK, " %.4f,%.4f", MU(x[0]), MU(y[0])); /* close path */
    }
  }
  fprintf(MASK, ";\n");
}

void egs_mskarc(int l, double w, double x1, double y1, double x2,
    double y2, double x3, double y3)
{
  if (drawlayer(l)) {
    if (mode & GRIDDED)
      fprintf(MASK,"add a%d :w%.3f :r1 %s%.3f,%.3f %.3f,%.3f %.3f,%.3f;\n",
	l,MU(w),mode&FILLED?":fill ":"",MU(x1),MU(y1),MU(x3),MU(y3),MU(x2),MU(y2));
    } else {
      fprintf(MASK,"add a%d :w%.4f :r1 %s%.4f,%.4f %.4f,%.4f %.4f,%.4f;\n",
	l,MU(w),mode&FILLED?":fill ":"",MU(x1),MU(y1),MU(x3),MU(y3),MU(x2),MU(y2));
    }
}

/* this routine doesn't seem to work with ADS or MDS, but is used by III-V
 * photonics because their viewer supports it and is more reliable than the
 * mskarc() routine which gives gaps at times.
 */
void egs_mskarc2 (int l, double w, double r, double a1, double a2, double x1,
    double y1)
{
  if (drawlayer(l)) {
    if (mode & GRIDDED) {
      fprintf(MASK,"add a%d :w%.3f :r1.000 %s:a %.3f %.3f %.3f %.3f,%.3f;\n",
	l,MU(w),mode&FILLED?":fill ":"",MU(r),DEG(a1),DEG(a2),MU(x1),MU(y1));
    } else {
      fprintf(MASK,"add a%d :w%.4f :r1.000 %s:a %.4f %.4f %.4f %.4f,%.4f;\n",
	l,MU(w),mode&FILLED?":fill ":"",MU(r),DEG(a1),DEG(a2),MU(x1),MU(y1));
    }
  }
}

void egs_msktext(int l, double a, double x, double y, double s,char *text)
{
  if (mode & GRIDDED) {
    fprintf(MASK,"add t%d :f%.3f %s:r%.3f '%s' %.3f %.3f;\n",
      l,MU(s),mode&FILLED?":fill ":"",a,text,MU(x),MU(y));
  } else {
    fprintf(MASK,"add t%d :f%.4f %s:r%.4f '%s' %.4f %.4f;\n",
      l,MU(s),mode&FILLED?":fill ":"",a,text,MU(x),MU(y));
  }
}

void egs_mskcircle(int l, double w, double x1, double y1, double x2, double y2)
{
  if (drawlayer(l)) {
    if (mode & GRIDDED) {
      fprintf(MASK, "add c%d :w%.3f :r5 %s%.3f %.3f %.3f %.3f;\n",
	l, MU(w), mode & FILLED ? ":fill " : "", MU(x1), MU(y1), MU(x2),
	MU(y2));
    } else {
      fprintf(MASK, "add c%d :w%.3f :r5 %s%.3f %.3f %.3f %.3f;\n",
	l, MU(w), mode & FILLED ? ":fill " : "", MU(x1), MU(y1), MU(x2),
	MU(y2));
    }
  }
}

void egs_mskpolystart(int l, double w)
{
  if (drawlayer(l)) {
    if (mode & GRIDDED) {
      fprintf(MASK,"add l%d :w%.3f%s",l,MU(w),mode&FILLED?" :fill":"");
    } else {
      fprintf(MASK,"add l%d :w%.4f%s",l,MU(w),mode&FILLED?" :fill":"");
    }
  }
}

void egs_mskpolypoint(int l, double x, double y)
{
  if (drawlayer(l)) {
    if (mode & GRIDDED) {
      fprintf(MASK," %.3f,%.3f",MU(x),MU(y));
    } else {
      fprintf(MASK," %.4f,%.4f",MU(x),MU(y));
    }
  }
}

void egs_mskpolygonend(int l)
{
  egs_mskpolyend(l);
}

void egs_mskpolyend(int l)
{
  if (drawlayer(l))
    fprintf(MASK,";\n");
}

void egs_mskpolygonstart(int l)
{
  if (drawlayer(l)) {
    if (mode & GRIDDED) {
      fprintf(MASK,"add p%d :w0.000 %s",l,mode&FILLED?":fill ":"");
    } else {
      fprintf(MASK,"add p%d :w0.0000 %s",l,mode&FILLED?":fill ":"");
    }
  }
}

void egs_msk_main_header(const char *filename)
{
  struct Layer *layer;
  int l=0;

  if (!strcmp(filename, "")) {
    MASK = stdout;
  } else if ((MASK = fopen(filename, "w")) == NULL) {
    fprintf(stderr, "Can't open '%s' for writing.\nError %d\n",
      filename, errno);
    exit(errno);
  }
  fprintf(MASK,"$$\n$$\n$$\n$$\n");
  if (mode & GRIDDED) {
    fprintf(MASK,"units um,1000.000;\n");
    fprintf(MASK,"grid 0.001,1 0.000,0.000;\n");
    fprintf(MASK,"lock 0.000;\n");
    fprintf(MASK,"tslant 0.000;\n");
    fprintf(MASK,"resolution 0.000;\n$$\n");
  } else {
    fprintf(MASK,"units um,10000.0000;\n");
    fprintf(MASK,"grid 0.0100,1000 0.0000,0.0000;\n");
    fprintf(MASK,"lock 0.0000;\n");
    fprintf(MASK,"tslant 0.0000;\n");
    fprintf(MASK,"resolution 0.0000;\n$$\n");
  }

  clayer = layers->number; /* set default layer to first layer defined */
  for (layer=layers;layer->number>-1;layer++)
    if (layer->visible)
      fprintf(MASK,"equ %s :d :l1 :c%d :p1 %d;\n",
              layer->name,layer->color,layer->number);

  fprintf(MASK,"exit;\n");
  fprintf(MASK,"$files ");
  if ((mode&FLATTENED) == 0)
    for (l = 0; l < num_layout - 1; l++)
      fprintf(MASK, "%s,", layouts[l].name);
  fprintf(MASK, "%s $;\n", layouts[l].name); /* main layout */
  fprintf(MASK,"edit;\nedit;\n");
}

void egs_msk_sublayout_header(const char *layout)
{
  layer(1);
  fprintf(MASK,"edit %s;\n",layout);
  fprintf(MASK,"show #e;\n");
  if (mode & GRIDDED) {
    fprintf(MASK,"lock 0.000;\n");
    fprintf(MASK,"level 1;\n");
    fprintf(MASK,"grid 0.001,1 0.000,0.000;\n");
  } else {
    fprintf(MASK,"lock 0.0000;\n");
    fprintf(MASK,"level 1;\n");
    fprintf(MASK,"grid 0.0001,1 0.0000,0.0000;\n");
  }
}

void egs_msk_sublayout_trailer()
{
  if (mode & GRIDDED) {
    fprintf(MASK,"grid 0.001,1 0.000,0.000;\n");
    fprintf(MASK,"lock 0.000;\n");
  } else {
    fprintf(MASK,"grid 0.0100,1000 0.0000,0.0000;\n");
    fprintf(MASK,"lock 0.0000;\n");
  }
  fprintf(MASK,"save;\n");
}

void egs_msk_trailer()
{
  egs_msk_sublayout_trailer();
}

void egs_mskline(int l, double w, double xb, double yb, double xe, double ye)
{
  if (drawlayer(l)) {
    if (mode & GRIDDED) {
      fprintf(MASK,"add l%d :w%.3f %s%.3f,%.3f %.3f,%.3f;\n",
	l,MU(w),mode&FILLED?":fill ":"",MU(xb),MU(yb),MU(xe),MU(ye));
    } else {
      fprintf(MASK,"add l%d :w%.4f %s%.4f,%.4f %.4f,%.4f;\n",
	l,MU(w),mode&FILLED?":fill ":"",MU(xb),MU(yb),MU(xe),MU(ye));
    }
  }
}

void egs_msklayout(const int layoutnr, const char *name, double a, double x, double y,int flip)
{
  if (mode & GRIDDED)
    fprintf(MASK,"add %s :R%.3f %s:ND %.3f %.3f;\n",name,DEG(a),
      ((flip==FLIP)?":mx ":""),MU(x),MU(y));
  else
    fprintf(MASK,"add %s :R%.4f %s:ND %.4f %.4f;\n",name,DEG(a),
      ((flip==FLIP)?":mx ":""),MU(x),MU(y));
}

